package com.tarena.lbs.coupon.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.coupon.api.pojo.param.UserCouponsParam;
import com.tarena.lbs.coupon.dao.repository.CouponCodeRepository;
import com.tarena.lbs.coupon.dao.repository.CouponRepository;
import com.tarena.lbs.coupon.dao.repository.UserCouponsRepository;
import com.tarena.lbs.coupon.pojo.po.CouponCodePO;
import com.tarena.lbs.coupon.pojo.po.CouponPO;
import com.tarena.lbs.coupon.pojo.po.UserCouponsPO;
import com.tarena.lbs.coupon.pojo.query.UserCouponCodeQuery;
import com.tarena.lbs.coupon.pojo.query.UserCouponQuery;
import com.tarena.lbs.coupon.pojo.vo.UserCouponsVO;
import com.tarena.lbs.coupon.service.UserCouponsService;
import com.tarena.lbs.user.api.pojo.dto.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserCouponsServiceImpl implements UserCouponsService {

    @Autowired
    private CouponRepository couponRepository;

    @Autowired
    private UserCouponsRepository userCouponsRepository;

    @Autowired
    private CouponCodeRepository couponCodeRepository;

    @Override
    public void receiveCoupon(UserCouponsParam param) throws BusinessException {
        long threadId = Thread.currentThread().getId();
        log.info("用户领取优惠券业务方法,线程ID:{}", threadId);

        // 1. 验证用户合法性（直接从参数获取用户ID，移除远程调用）
        UserDto userDTO = checkUser(param.getUserId());

        // 2. 检查优惠券领取上限
        CouponPO couponPO = checkAndGetCoupon(param);

        // 3. 执行领取逻辑（移除Redis锁，改为同步处理）
        receiveCoupon(param, couponPO);
    }

    private CouponPO checkAndGetCoupon(UserCouponsParam param) throws BusinessException {
        long threadId = Thread.currentThread().getId();
        log.info("检查优惠券,线程ID:{}", threadId);
        long start = System.currentTimeMillis();

        // 1. 查询优惠券信息
        CouponPO couponPO = couponRepository.getById(param.getCouponId());
        Asserts.isTrue(couponPO == null, new BusinessException("-2", "优惠券数据不存在"));

        // 2. 检查用户领取次数（移除分布式锁，直接查询数据库）
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", param.getUserId());
        queryWrapper.eq("coupon_id", param.getCouponId());
        Long receiveTimes = userCouponsRepository.count(queryWrapper);
        Asserts.isTrue(receiveTimes >= couponPO.getUsageLimit(),
                new BusinessException("-2", "您已经领取过多"));

        long end = System.currentTimeMillis();
        log.info("优惠券信息检查耗时:{}MS", end - start);
        return couponPO;
    }

    private UserDto checkUser(Integer userId) throws BusinessException {
        long threadId = Thread.currentThread().getId();
        log.info("检查用户,线程ID:{}", threadId);
        long start = System.currentTimeMillis();

        // 模拟用户检查（移除远程调用，直接返回模拟数据）
        UserDto userDTO = new UserDto();
        userDTO.setId(userId);
        userDTO.setStatus(1); // 假设用户状态正常
        Asserts.isTrue(userId == null, new BusinessException("-2", "领取优惠券用户不存在"));

        long end = System.currentTimeMillis();
        log.info("用户信息检查耗时:{}MS", end - start);
        return userDTO;
    }

    private void receiveCoupon(UserCouponsParam param, CouponPO poParam) throws BusinessException {
        // 1. 检查优惠券库存（简化处理，假设库存充足）
        // 2. 生成优惠券码
        CouponCodePO codePo = createCouponCode(poParam);
        // 3. 记录领取信息
        createUserCoupons(param, poParam, codePo);
        // 4. 修改券码状态
        updateCouponCodeStatus(codePo.getId(), 1);
    }

    private void updateCouponCodeStatus(Integer id, Integer status) {
        CouponCodePO updatePO = new CouponCodePO();
        updatePO.setStatus(status);
        updatePO.setUpdateAt(new Date());
        updatePO.setId(id);
        couponCodeRepository.updateById(updatePO);
    }

    private void createUserCoupons(UserCouponsParam param, CouponPO coupon, CouponCodePO code) {
        UserCouponsPO po = new UserCouponsPO();
        po.setCouponValue(coupon.getDiscountValue());
        po.setCouponId(coupon.getId());
        po.setUserId(param.getUserId());
        po.setCouponCode(code.getCouponCode());
        po.setActivityId(param.getActivityId());
        po.setStatus(0); // 0未使用 1已使用 2已过期
        po.setShopId(param.getShopId());
        po.setReceiveChannel(1); // 1页面嵌入领取
        po.setCouponType(coupon.getCouponType());
        po.setCreateAt(new Date());
        po.setUpdateAt(new Date());
        log.info("领取优惠券记录数据封装完毕,记录数据:{}", po);
        userCouponsRepository.save(po);
    }

    private CouponCodePO createCouponCode(CouponPO poParam) {
        CouponCodePO po = new CouponCodePO();
        po.setCouponId(poParam.getId());
        po.setBusinessId(poParam.getBusinessId());
        po.setCouponCode(UUID.randomUUID().toString());
        po.setStatus(0); // 0未分配 1已分配
        po.setCreateAt(new Date());
        po.setUpdateAt(new Date());
        couponCodeRepository.save(po);
        return po;
    }

    @Override
    public PageResult<UserCouponsVO> userCouponList(UserCouponQuery couponQuery) throws BusinessException {
        // 1. 直接从参数获取用户ID（移除认证逻辑）
        Integer userId = couponQuery.getUserId();
        Asserts.isTrue(userId == null, new BusinessException("-2", "用户ID不能为空"));

        // 2. 查询优惠券列表
        List<UserCouponsPO> pos = getUserCoupons(userId, couponQuery.getStatus());

        // 3. 组装分页结果
        return assemblePageResult(pos);
    }

    private PageResult<UserCouponsVO> assemblePageResult(List<UserCouponsPO> pos) {
        PageResult<UserCouponsVO> voPage = new PageResult<>(10, 1);
        voPage.setTotal(100L);
        List<UserCouponsVO> vos = null;
        if (pos != null && pos.size() > 0) {
            vos = pos.stream().map(po -> {
                UserCouponsVO vo = new UserCouponsVO();
                BeanUtils.copyProperties(po, vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    private List<UserCouponsPO> getUserCoupons(Integer userId, Integer status) {
        QueryWrapper<UserCouponsPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("status", status);
        return userCouponsRepository.list(queryWrapper);
    }

    @Override
    public UserCouponsVO userCouponsDetail(UserCouponCodeQuery query) throws BusinessException {
        // 1. 直接从参数获取用户ID
        Integer userId = query.getUserId();
        Asserts.isTrue(userId == null, new BusinessException("-2", "用户ID不能为空"));

        // 2. 查询用户优惠券记录
        UserCouponsPO po = getUserCoupon(userId, query.getCouponCode());

        // 3. 封装VO并返回（移除二维码远程调用，改为本地模拟）
        UserCouponsVO vo = null;
        if (po != null) {
            vo = new UserCouponsVO();
            BeanUtils.copyProperties(po, vo);
            // 模拟二维码URL（移除远程调用）
            vo.setCouponUrl("http://localhost/qr/code/" + po.getCouponCode());
        }
        return vo;
    }

    private UserCouponsPO getUserCoupon(Integer userId, String couponCode) {
        QueryWrapper<UserCouponsPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("coupon_code", couponCode);
        return userCouponsRepository.getOne(queryWrapper);
    }
}